from fastapi import Depends
from sqlmodel import select, func, delete, between, insert, update, and_
import typing as T
import logging


from . import table
from ..init.Global import Session
from ..dto.PageParam import PageParam
from ..dto.Emp import Emp


class _EmpMapper:
    def __call__(self, session: Session):
        self.session = session
        return self

    def _parserPageParam(self, pageParam: PageParam):
        conditions = []
        if pageParam.name:
            conditions.append(
                table.empTable.name.like(func.concat("%", pageParam.name, "%"))
            )
        if pageParam.gender:
            conditions.append(table.empTable.gender == pageParam.gender)
        if pageParam.begin and pageParam.end:
            conditions.append(
                between(
                    table.empTable.entrydate,
                    pageParam.begin,
                    pageParam.end,
                )
            )
        return conditions

    async def list(self, pageParam: PageParam):
        query = select(table.empTable)
        conditions = self._parserPageParam(pageParam)
        query = query.where(*conditions)
        query = query.offset(pageParam.page).limit(pageParam.pageSize)
        result = (await self.session.execute(query)).scalars().all()
        logging.info(f"EmpMapper.list() result: {result}")
        return result

    async def count(self, pageParam: PageParam):
        conditions = self._parserPageParam(pageParam)
        result = (
            await self.session.execute(
                select(func.count()).select_from(table.empTable).where(*conditions)
            )
        ).scalar()
        logging.info(f"EmpMapper.count() result: {result}")
        return result

    async def delete(self, ids: T.List[int]):
        await self.session.execute(
            delete(table.empTable).where(table.empTable.id.in_(ids))
        )

    async def save(self, emp: Emp):
        await self.session.execute(
            insert(table.empTable).values(**emp.model_dump(exclude_none=True))
        )

    async def getById(self, id: int):
        result = (
            await self.session.execute(
                select(table.empTable).where(table.empTable.id == id)
            )
        ).scalar()
        logging.info(f"EmpMapper.getById() result: {result}")
        return result

    async def update(self, emp: Emp):
        await self.session.execute(
            update(table.empTable)
            .where(table.empTable.id == emp.id)
            .values(**emp.model_dump(exclude_none=True))
        )

    async def login(self, username: str, password: str):
        result = (
            await self.session.execute(
                select(table.empTable).where(
                    and_(
                        table.empTable.username == username,
                        table.empTable.password == password,
                    )
                )
            )
        ).scalar()
        logging.info(f"EmpMapper.loogin() result: {result}")
        return result


EmpsMapper = T.Annotated[_EmpMapper, Depends(_EmpMapper())]
